import { SetupContext, ref } from 'vue';
import { FilterBarProps } from '../filter-bar.props';
import { FilterItem } from '../types';
import { UseFilterItems } from './types';
import { Condition, FieldConfig } from '../../../condition/src/types';
import { ConditionValue } from '../../../condition/src/composition/condition-value/types';
import { useConditionValue } from '../../../condition/src/composition/use-condition-value';

export function useFilterItems(props: FilterBarProps, context: SetupContext): UseFilterItems {
    const filterConditions = ref<Condition[]>([]);
    const filterFields = ref<FieldConfig[]>([]);
    const filterItems = ref<FilterItem[]>([]);
    const currentFilterId = ref('');
    const disabled = ref(false);
    const mode = ref(props.mode);
    const fieldMap = new Map<string, FieldConfig>();
    const useConditionValueComposition = useConditionValue();

    function shouldShowClearButtonInFilterItem(filterItem: FilterItem) {
        return !disabled.value && mode.value === 'display-only' && !!filterItem.hasValue && !!filterItem.displayText;
    }

    function loadFieldConfigs(fields: FieldConfig[]) {
        filterFields.value = fields;
        filterFields.value.reduce((result: Map<string, FieldConfig>, field: FieldConfig) => {
            result.set(field.labelCode, field);
            return result;
        }, fieldMap);
    }

    function loadConditions(conditions: Condition[]) {
        filterConditions.value = conditions.map((condition: Condition, index: number) => {
            if (typeof condition.value === 'string') {
                const editorType = fieldMap.get(condition.fieldCode)?.editor.type || 'text';
                condition.value = useConditionValueComposition.createConditionValue(editorType, { value: condition.value });
            }
            condition.conditionId = index;
            return condition;
        });
    }

    function buildFilterItems(): FilterItem[] {
        const filterItems: FilterItem[] = filterFields.value.map((fieldField: FieldConfig) => {
            const filterItem: FilterItem = {
                id: fieldField.id,
                fieldCode: fieldField.code,
                fieldName: fieldField.name,
                editor: fieldField.editor
            };
            return filterItem;
        });
        filterConditions.value.reduce<FilterItem[]>((filterItems: FilterItem[], filterCondition: Condition, index: number) => {
            const matchedFilterItem = filterItems.find((item: FilterItem) => item.fieldCode === filterCondition.fieldCode);
            if (matchedFilterItem) {
                matchedFilterItem.displayText = (filterCondition.value as ConditionValue).getValue();
                matchedFilterItem.hasValue = true;
            }
            return filterItems;
        }, filterItems);
        return filterItems;
    }

    function loadFilterItems(fields: FieldConfig[], conditions: Condition[]) {
        loadFieldConfigs(props.fields);
        loadConditions(props.data);
        filterItems.value = buildFilterItems();
    }

    function removeFilterItem(itemToBeRemoved: FilterItem) {
        filterItems.value = filterItems.value.filter((item: FilterItem) => item.id !== itemToBeRemoved.id);
        filterConditions.value = filterConditions.value.filter((condition: Condition) => {
            return condition.fieldCode !== itemToBeRemoved.fieldCode;
        });
        filterFields.value = filterFields.value.filter((field: FieldConfig) => field.id !== itemToBeRemoved.id);
        context.emit('Remove', itemToBeRemoved.fieldCode);
    }

    function clearFilterItem(itemToBeClear: FilterItem) {
        itemToBeClear.displayText = '';
        itemToBeClear.hasValue = false;
        filterConditions.value = filterConditions.value.filter((condition: Condition) => {
            return condition.fieldCode !== itemToBeClear.fieldCode;
        });
        context.emit('Clear', itemToBeClear.fieldCode);
    }

    function clearAll() {
        filterItems.value = [];
        filterConditions.value = [];
        filterFields.value = [];
        context.emit('Reset');
    }

    function reset() {
        filterItems.value.forEach((itemToBeClear: FilterItem) => {
            itemToBeClear.displayText = '';
            itemToBeClear.hasValue = false;
        });
        filterConditions.value = [];
        context.emit('Reset');
    }

    loadFilterItems(props.fields, props.data);

    return {
        clearAll, clearFilterItem, currentFilterId, filterFields, filterItems,
        loadFilterItems, removeFilterItem, reset, shouldShowClearButtonInFilterItem
    };
}
